package com.wn.access.service.impl;

import java.util.Date;
import java.util.Objects;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.wn.access.entity.TradeLog;
import com.wn.access.mapper.TradeLogMapper;
import com.wn.access.service.ITradeLogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wn.access.utils.BaseResult;
import com.wn.access.utils.EncodeUtil;
import com.wn.common.model.dto.bank.BankCardAddDTO;
import com.wn.common.model.dto.trade.bid.BankBidDTO;
import com.wn.common.model.dto.trade.bid.BidBalanceDTO;
import com.wn.common.model.dto.trade.bid.BorrowRecordStatusDTO;
import com.wn.common.model.vo.bank.SignatureVo;
import com.wn.common.model.vo.borrow.BorrowRecordVo;
import com.wn.common.model.vo.pay.RepayVo;
import com.wn.common.model.vo.trade.bid.LoanVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

/**
 * <p>
 * 托管系统交易记录表 服务实现类
 * </p>
 *
 * @author yellow docker
 * @since 2023-03-01
 */
@Service
@Slf4j
public class TradeLogServiceImpl extends ServiceImpl<TradeLogMapper, TradeLog> implements ITradeLogService {

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 记录交易日志
     *
     * @param bankCardAddDTO
     * @return
     */
    @Override
    public SignatureVo savelog(BankCardAddDTO bankCardAddDTO) {

        TradeLog tradeLog = new TradeLog();

        tradeLog.setReqCode(bankCardAddDTO.getReqCode());  // 流水号

        //请求类型
        tradeLog.setReqType("USER_CARD_CREATE");

        tradeLog.setObjectId(bankCardAddDTO.getUserId());
        //创建事件
        tradeLog.setCreateDate(new Date());

        //数据未同步
        tradeLog.setSynchronizeStatus(0);
        //返回的数据
        tradeLog.setResponseData("返回银行的给的数据");

        //记录日志
        save(tradeLog);

        log.info("托管系统访问银行 给我返回了数据.... ");
        //返回 托管开户请求数据
        String reqData = JSON.toJSONString(bankCardAddDTO);
        SignatureVo signatureVo = new SignatureVo();
        //调用接口名称
        signatureVo.setServiceName("BANK_SERVICE_REGISTER");
        // sdd 编号
        signatureVo.setPlatformNo("SDDFP");
        //请求的数据 进行加密
        signatureVo.setReqData(EncodeUtil.encodeURL(EncodeUtil.encodeBase64(reqData)));
        signatureVo.setBankUrl("http://localhost:5600/bank/user");

        return signatureVo;

    }

    //trade_log 的数据同步
    @Override
    public void updateSyncStatus(String reqCode) {

        update(Wrappers.lambdaUpdate(TradeLog.class)
                .set(TradeLog::getSynchronizeStatus, 1)
                .set(TradeLog::getConfirmDate, new Date())
                .eq(TradeLog::getReqCode, reqCode)
        );
    }

    @Override
    public BaseResult syncBorrowRecord(BorrowRecordVo borrowRecordVo) {

        //01 创建 tradeLog 进行保存
        TradeLog tradeLog = new TradeLog();
        tradeLog.setReqCode(borrowRecordVo.getReqCode());
        tradeLog.setReqType("SYNC_BORROW_RECORD");
        tradeLog.setObjectId(borrowRecordVo.getUserId());
        tradeLog.setCreateDate(new Date());
        //未同步
        tradeLog.setSynchronizeStatus(0);

        //通过流水号判断 日志是否已存在
        TradeLog tradeLogOld = getOne(Wrappers.lambdaQuery(TradeLog.class)
                .eq(TradeLog::getReqCode, borrowRecordVo.getReqCode()));

        if (Objects.isNull(tradeLogOld)) {
            //保存
            save(tradeLog);
        } else {
            //已存在 直接返回
            BaseResult baseResult = new BaseResult();
            baseResult.setRespMsg("审核以通过不用重复");
            baseResult.setStatus(200);
            return baseResult;
        }

        //02 给银行系统发送数据
        log.info("给银行系统发送数据....");

        String jsonString = JSON.toJSONString(borrowRecordVo);

        //加密
        String reqData = EncodeUtil.encodeBase64(jsonString);

        // 数据能直接发送吗
        //请求的url的编码 (网络传输中,特殊符号的传输需要  url重写  )
        reqData = EncodeUtil.encodeURL(reqData);

        //给指定的银行的 地址发送数据
        String url = "http://localhost:5600/service";

        String serviceName = "SYNC_BORROW_RECORD";
        // 怎么发送
        BaseResult baseResult = sendHttp(url, reqData, serviceName, tradeLog);

        //03 返回银行系统数据 ( 更新日志同步 )
        log.info("日志同步");
        baseResult.setRespMsg("审核成功");
        baseResult.setStatus(200);

        return baseResult;
    }

    @Override
    public BidBalanceDTO getBidBalance(String userCode) {

        String url = "http://localhost:5600";
        String requestUrl = url + "/bid/balance/" + userCode;

        //给银行 发送数据 拿到 用户的余额
        BidBalanceDTO bankBidDTO = restTemplate.getForObject(requestUrl, BidBalanceDTO.class);

        return bankBidDTO;
    }

    @Override
    public BaseResult bankBidService(BankBidDTO bankBidDTO) {

        //日志的记录
        TradeLog tradeLog = new TradeLog();

        tradeLog.setReqCode(bankBidDTO.getReqCode());
        tradeLog.setReqType(bankBidDTO.getBizType());
        tradeLog.setObjectId(bankBidDTO.getId());
        tradeLog.setCreateDate(new Date());
        tradeLog.setSynchronizeStatus(0);

        //通过流水号判断 日志是否已存在
        TradeLog tradeLogOld = getOne(Wrappers.lambdaQuery(TradeLog.class).eq(TradeLog::getReqCode, bankBidDTO.getReqCode()));

        if (Objects.isNull(tradeLogOld)) {
            //保存
            save(tradeLog);
        } else {
            //已存在 直接返回
            BaseResult baseResult = new BaseResult();
            baseResult.setRespMsg("成功");
            baseResult.setStatus(200);
            return baseResult;
        }
        //给银行发送数据
        String reqData = EncodeUtil.encodeBase64(JSON.toJSONString(bankBidDTO));
        reqData = EncodeUtil.encodeURL(reqData);

        String url = "http://localhost:5600/service";
        String serviceName = "AGENCY_BID";
        BaseResult baseResult = sendHttp(url, reqData,serviceName,tradeLog);

        log.info("远程发送数据到银行成功....");

        return baseResult;

    }

    @Override
    public BaseResult confirmLoan(LoanVo loanVo) {

        //日志的记录
        TradeLog tradeLog = new TradeLog();

        tradeLog.setReqCode(loanVo.getReqCode());
        tradeLog.setReqType("LoanRequest");
        tradeLog.setObjectId(loanVo.getId());
        tradeLog.setCreateDate(new Date());
        tradeLog.setSynchronizeStatus(0);

        //通过流水号判断 日志是否已存在
        TradeLog tradeLogOld = getOne(Wrappers.lambdaQuery(TradeLog.class).eq(TradeLog::getReqCode, loanVo.getReqCode()));

        if (Objects.isNull(tradeLogOld)) {
            //保存
            save(tradeLog);
        } else {
            //已存在 直接返回
            BaseResult baseResult = new BaseResult();
            baseResult.setRespMsg("成功");
            baseResult.setStatus(200);
            return baseResult;
        }
        //发送请求  把 投资人的 钱转给  借款人
        String url ="http://localhost:5600/service";
        String reqData = EncodeUtil.encodeBase64(JSON.toJSONString(loanVo));
        reqData = EncodeUtil.encodeURL(reqData);
        String serviceName = "CONFIRM_LOAN";
        BaseResult baseResult = sendHttp(url, reqData, serviceName, tradeLog);

        return baseResult;
    }

    //修改借款记录的状态
    @Override
    public BaseResult updateBorrowRecordStatus(BorrowRecordStatusDTO borrowRecordStatusDTO) {

        //01 记录日志
        TradeLog tradeLog = new TradeLog();

        tradeLog.setReqCode(borrowRecordStatusDTO.getReqCode());
        tradeLog.setReqType("BorrowRecord");
        tradeLog.setObjectId(borrowRecordStatusDTO.getBorrowRecordId());
        tradeLog.setCreateDate(new Date());
        tradeLog.setSynchronizeStatus(0);

        //通过流水号判断 日志是否已存在
        TradeLog tradeLogOld = getOne(Wrappers.lambdaQuery(TradeLog.class).eq(TradeLog::getReqCode, borrowRecordStatusDTO.getReqCode()));

        if (Objects.isNull(tradeLogOld)) {
            //保存
            save(tradeLog);
        } else {
            //已存在 直接返回
            BaseResult baseResult = new BaseResult();
            baseResult.setRespMsg("成功");
            baseResult.setStatus(200);
            return baseResult;
        }
        //02 发送数据 给银行系统
        //发送请求  把银行系统那边的  借款记录进行修改  状态改为放款
        String url ="http://localhost:5600/service";
        String reqData = EncodeUtil.encodeBase64(JSON.toJSONString(borrowRecordStatusDTO));
        reqData = EncodeUtil.encodeURL(reqData);
        String serviceName = "UPDATE_BORROW_STATUS";
        BaseResult baseResult = sendHttp(url, reqData, serviceName, tradeLog);

        return baseResult;
    }

    //还款确认的数据发送
    // （ 借款人冻结的金额 转发给  投资人  ）
    // （ 借款人冻结的金额  为0   ）
    // （ 投资人的金额     +  借款人冻结的金额  ）
    @Override
    public BaseResult confirmRepay(RepayVo repayVo) {

        //01 记录日志
        TradeLog tradeLog = new TradeLog();

        tradeLog.setReqCode(repayVo.getReqCode());
        tradeLog.setReqType("Repayment");
        tradeLog.setObjectId(repayVo.getId());
        tradeLog.setCreateDate(new Date());
        tradeLog.setSynchronizeStatus(0);

        //通过流水号判断 日志是否已存在
        TradeLog tradeLogOld = getOne(Wrappers.lambdaQuery(TradeLog.class)
                .eq(TradeLog::getReqCode, repayVo.getReqCode()));

        if (Objects.isNull(tradeLogOld)) {
            //保存
            save(tradeLog);
        } else {
            //已存在 直接返回
            BaseResult baseResult = new BaseResult();
            baseResult.setRespMsg("成功");
            baseResult.setStatus(200);
            return baseResult;
        }
        //02 发送数据 给银行系统
        //发送请求  把银行系统那边的  借款记录进行修改  状态改为放款
        String url ="http://localhost:5600/service";
        log.info("发送数据进行远程调用repayVo....{}",repayVo);
        String reqData = EncodeUtil.encodeBase64(JSON.toJSONString(repayVo));
        reqData = EncodeUtil.encodeURL(reqData);
        String serviceName = "CONFIRM_REPAYMENT";
        BaseResult baseResult = sendHttp(url, reqData, serviceName, tradeLog);

        return baseResult;
    }

    /**
     * 给银行发送数据
     *
     * @param url
     * @param reqData
     * @param tradeLog
     * @return
     */
    private BaseResult sendHttp(String url, String reqData, String serviceName, TradeLog tradeLog) {

        String requestUrl = url + "?reqData=" + reqData + "&serviceName=" + serviceName;
//        String reqUrl = "http://localhost:5600/service?reqData=xxx&serviceName=SYNC_BORROW_RECORD";
        log.info("请求银行存管，url：{}", requestUrl);
        //从银行获取数据
        String responseBody = restTemplate.getForObject(requestUrl, String.class);
        //解析结果
        BaseResult baseResult = JSON.parseObject(responseBody, BaseResult.class);

        //日志同步
        //修改日志  tradeLog
        tradeLog.setSynchronizeStatus(1);   //同步
        tradeLog.setResponseData(responseBody); //银行返回的结果
        tradeLog.setConfirmDate(new Date());    //确认时间

        this.updateById(tradeLog);

        return baseResult;
    }

}
